package com.pz.cloud.framework.base.dao;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.pz.cloud.framework.base.model.BasePage;
import com.pz.cloud.framework.base.model.Pageable;
import com.pz.cloud.framework.model.AbstractSqlBuilder;
import com.pz.cloud.framework.model.SqlBuilder;
import com.pz.cloud.framework.util.SqlUtil;
import com.pz.cloud.framework.util.ThreadTaskUtil;
import org.apache.poi.ss.formula.functions.T;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.jeecg.common.util.BeanConvertUtil;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 业务公共dao
 * 3hmzz
 */
@Repository
public class CommonDao {

    @PersistenceContext
    protected EntityManager entityManager;

    public EntityManager getEntityManager(){
        return  entityManager;
    }
    public boolean execute(String sql,Map<String,Object>parms){
        Query query = entityManager.createNativeQuery(sql);
        if(parms!=null&&parms.size()>0){
            SqlUtil.setQueryParams(parms,query);
        }
        int i = query.executeUpdate();
        return i>0;
    }
    public <T> IPage findPage(T entity){
        SqlBuilder sqlBuilder = SqlBuilder.init(entity, null);
        return findPage(sqlBuilder);
    }
    public <T> List findList(T entity){
        SqlBuilder sqlBuilder = SqlBuilder.init(entity, null);
        return findList(sqlBuilder);
    }
    public IPage findPage(AbstractSqlBuilder sqlBuilder){
        Query query = entityManager.createNativeQuery(sqlBuilder.getSql());
        SqlUtil.setQueryParams(sqlBuilder.getParmMap(),query);

        Pageable pageable = sqlBuilder.getPage();
        boolean bPage = pageable!=null&&pageable.getPaging();
        IPage page;
        if(bPage){
            query.setFirstResult((pageable.getPageNo()-1)* pageable.getPageSize());
            query.setMaxResults(pageable.getPageSize());

            Query countQuery = entityManager.createNativeQuery(sqlBuilder.getCountSql());
            SqlUtil.setQueryParams(sqlBuilder.getParmMap(),countQuery);

            page  = findPage(query, countQuery, sqlBuilder.getReturnType());
            page.setSize(pageable.getPageSize());
            page.setCurrent(pageable.getPageNo());
        }else{
            page = findPage(query, sqlBuilder.getReturnType());
        }
        return page;
    }
    public List findList(AbstractSqlBuilder sqlBuilder){
        sqlBuilder.page(null);
        IPage page = findPage(sqlBuilder);
        return page.getRecords();
    }
    public <T> T findOne(AbstractSqlBuilder sqlBuilder){
        sqlBuilder.page(null);
        IPage page = findPage(sqlBuilder);
        List<T> records = page.getRecords();
        if(!CollectionUtils.isEmpty(records)){
            return records.get(0);
        }
        return  null;
    }


    private IPage findPage(Query query, Query countQuery,Class cla) {
        List<String> tasks = Arrays.asList("sql", "count");
        final Map<String,Object> map = new HashMap<>();
        query.unwrap(SQLQuery.class).setResultTransformer(	Transformers.ALIAS_TO_ENTITY_MAP);

        ThreadTaskUtil.excute(tasks, t-> {
            if("sql".equals(t)){
                query.unwrap(SQLQuery.class).setResultTransformer(	Transformers.ALIAS_TO_ENTITY_MAP);
                List list = query.getResultList();

                if(cla!=null){
                    list = BeanConvertUtil.convert(list,cla,true);
                }
                map.put("list",list);
            }else{
                int count = 0;
                try{
                    Object singleResult = countQuery.getSingleResult();
                    if(singleResult!=null){
                        count = Integer.parseInt(singleResult.toString());
                    }
                }catch (Exception e){
                    query.setFirstResult(0);
                    query.setMaxResults(Integer.MAX_VALUE);
                    count =  query.getResultList().size();
                }
                map.put("count",count);
            }
            return null;
        });
        BasePage basePage = BasePage.build((List)map.get("list"), (Integer) map.get("count"));
        return basePage;
    }

    private BasePage findPage(Query query, Class cla) {
        query.unwrap(SQLQuery.class).setResultTransformer(	Transformers.ALIAS_TO_ENTITY_MAP);
        List list = query.getResultList();

        if(cla!=null){
            list = BeanConvertUtil.convert(list,cla,true);
        }

        BasePage basePage = BasePage.build(list, list.size());
        return basePage;
    }


}


